package com.qupai.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.qupai.constant.MessageConstant;
import com.qupai.context.BaseContext;
import com.qupai.dto.CancelRegistrationDTO;
import com.qupai.dto.RegistrationDTO;
import com.qupai.dto.RegistrationPageQueryDTO;
import com.qupai.dto.RegistrationRejectionDTO;
import com.qupai.entity.Activities;
import com.qupai.entity.Registration;
import com.qupai.entity.User;
import com.qupai.exception.ActivitiesException;
import com.qupai.exception.RegistrationException;
import com.qupai.mapper.ActivitiesMapper;
import com.qupai.mapper.RegistrationMapper;
import com.qupai.mapper.UserMapper;
import com.qupai.result.PageResult;
import com.qupai.service.IRegistrationService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qupai.vo.CertificateVO;
import com.qupai.vo.RegistrationVO;
import jakarta.annotation.Resource;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDateTime;

/**
 * <p>
 * 活动报名表 服务实现类
 * </p>
 *
 * @author bluefoxyu
 * @since 2024-03-17
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class RegistrationServiceImpl extends ServiceImpl<RegistrationMapper, Registration> implements IRegistrationService {

    private final RegistrationMapper registrationMapper;
    private final ActivitiesMapper activitiesMapper;
    private final UserMapper userMapper;

    /**
     * 报名活动
     */
    @Override
    public CertificateVO signUp(RegistrationDTO registrationDTO) {
        //获取当前用户id
        Long userId= BaseContext.getCurrentId();

        //默认活动开始后第二天才能报名
        QueryWrapper<Activities>activitiesQueryWrapper=new QueryWrapper<>();
        activitiesQueryWrapper.lambda()
                .eq(Activities::getId,registrationDTO.getActivityId())
                .eq(Activities::getCollegesId,registrationDTO.getActivityCollegesId())
                .eq(Activities::getOrganizationsId,registrationDTO.getActivityOrganizationsId());
        Activities activities = activitiesMapper.selectOne(activitiesQueryWrapper);
        if (activities==null){
            //活动存在
            throw new ActivitiesException(MessageConstant.ACTIVITIES_NOT_FOUND);
        }

        LocalDateTime plusDays = activities.getOnShelfTime().plusDays(1);
        if (LocalDateTime.now().isBefore(plusDays)){
            //活动开始后第二天才能报名
            throw new RegistrationException(MessageConstant.AFTER_DAY_CAN_SIGN_UP_ACTIVITIES);
        }

        if (activities.getOffShelfTime().isBefore(LocalDateTime.now())){
            //活动结束不能报名
            throw new RegistrationException(MessageConstant.ACTIVITIES_HAVE_ENDED);
        }

        QueryWrapper<Registration> queryWrapper=new QueryWrapper<>();
        queryWrapper.lambda()
                .eq(Registration::getUserId,userId)
                .eq(Registration::getActivityId,registrationDTO.getActivityId())
                .eq(Registration::getActivityCollegesId,registrationDTO.getActivityCollegesId())
                .eq(Registration::getActivityOrganizationsId,registrationDTO.getActivityOrganizationsId());

        //判断是否已经报名
        Registration registration = registrationMapper.selectOne(queryWrapper);
        if (registration!=null){
            throw new RegistrationException(MessageConstant.NO_NEED_TO_REPEAT_REGISTRATION);
        }

        //如果为空，重新给他分配一个空间
        registration=new Registration();
        registration.setActivityImage(activities.getImage());
        registration.setActivityCoins(activities.getActivityCoins());
        //将前端传过来的数据封装到registration对象中
        BeanUtils.copyProperties(registrationDTO,registration);
        User user=userMapper.selectById(userId);
        registration.setUserId(userId);
        registration.setUserName(user.getName());
        registration.setUserCollegesId(user.getCollegesId());
        registration.setUserMajor(user.getMajor());
        registration.setUserClassName(user.getClassName());
        registration.setUserPhone(user.getPhone());
        registration.setUserStudentId(user.getStudentId());
        BeanUtils.copyProperties(user,registration);
        registration.setSignUpTime(LocalDateTime.now());

        //设置状态信息,已报名
        registration.setStatus(Registration.IS_REGISTERED);

        System.out.println(registration);
        log.info("报名成功，报名信息为：{}",registration);
        //给报名表插入数据
        registrationMapper.insert(registration);

        CertificateVO certificateVO=new CertificateVO();
        BeanUtils.copyProperties(registration,certificateVO);

        return certificateVO;
    }

    /**
     * 取消报名活动
     */
    @Override
    public void cancel(CancelRegistrationDTO cancelRegistrationDTO) {
        //获取当前用户id
        Long userId= BaseContext.getCurrentId();

        QueryWrapper<Registration> queryWrapper=new QueryWrapper<>();
        queryWrapper.lambda()
                .eq(Registration::getUserId,userId)
                .eq(Registration::getActivityId,cancelRegistrationDTO.getActivityId())
                .eq(Registration::getActivityCollegesId,cancelRegistrationDTO.getActivityCollegesId())
                .eq(Registration::getActivityOrganizationsId,cancelRegistrationDTO.getActivityOrganizationsId());
        Registration registration = registrationMapper.selectOne(queryWrapper);
        if (registration==null) {
            throw new RegistrationException(MessageConstant.NO_HAVE_REGISTRATION);
        }
        //删除该报名信息，取消报名
        registrationMapper.deleteById(registration.getId());
    }

    /**
     * 报名分页查询
     */
    @Override
    public PageResult conditionSearch(RegistrationPageQueryDTO registrationPageQueryDTO) {
        Page<Registration> page = Page.of(registrationPageQueryDTO.getPageNo(), registrationPageQueryDTO.getPageSize());

        //查询条件分页查询
        Page<Registration> p = lambdaQuery()
                .eq(registrationPageQueryDTO.getUserId()!=null,Registration::getUserId, registrationPageQueryDTO.getUserId())
                .eq(registrationPageQueryDTO.getStatus()!=null,Registration::getStatus, registrationPageQueryDTO.getStatus())
                .eq(registrationPageQueryDTO.getActivityCollegesId() != null, Registration::getActivityId,
                        registrationPageQueryDTO.getActivityCollegesId())
                .eq(registrationPageQueryDTO.getStatus()!=null,Registration::getStatus,
                        registrationPageQueryDTO.getStatus())
                .like(registrationPageQueryDTO.getUserName() != null, Registration::getUserName,
                        registrationPageQueryDTO.getUserName())
                .like(registrationPageQueryDTO.getUserStudentId() != null, Registration::getUserStudentId,
                        registrationPageQueryDTO.getUserStudentId())
                .like(registrationPageQueryDTO.getUserPhone() != null, Registration::getUserPhone,
                        registrationPageQueryDTO.getUserPhone())
                .ge(registrationPageQueryDTO.getSignUpTime()!=null,Registration::getSignUpTime,
                        registrationPageQueryDTO.getSignUpTime())
                .orderByDesc(Registration::getSignUpTime)
                .page(page);

        return new PageResult(p.getTotal(),p.getPages(),p.getRecords());
    }


    /**
     * 完成报名
     */
    @Override
    public RegistrationVO complete(Long id) {
        Registration registration = registrationMapper.selectById(id);

        // 判断是否已经报名
        if (registration==null||!registration.getStatus().equals(Registration.IS_REGISTERED)){
            throw new RegistrationException(MessageConstant.APPLY_STATUS_ERROR);
        }

        //赋予用户志愿币
        BigDecimal coins = registration.getActivityCoins();
        Long userId = registration.getUserId();
        User user = userMapper.selectById(userId);
        BigDecimal walletVolunteer = user.getWalletVolunteer();
        user.setWalletVolunteer(walletVolunteer.add(coins));
        userMapper.updateById(user);

        //修改报名状态
        registration.setStatus(Registration.COMPLETED);
        registration.setCompleteTime(LocalDateTime.now());

        //补充完成信息，填写工作人员信息
        Long employeeId = BaseContext.getCurrentId();
        registration.setCompleteEmployee(employeeId);
        registrationMapper.updateById(registration);

        RegistrationVO registrationVO=new RegistrationVO();
        BeanUtils.copyProperties(registration,registrationVO);
        return registrationVO;
    }

    @Override
    public void rejection(RegistrationRejectionDTO registrationRejectionDTO) {
        Long id = registrationRejectionDTO.getId();
        String reason = registrationRejectionDTO.getRejectionReason();
        Registration registration = registrationMapper.selectById(id);
        if (registration==null||!registration.getStatus().equals(Registration.IS_REGISTERED)){
            throw new RegistrationException(MessageConstant.APPLY_STATUS_ERROR);
        }
        registration.setStatus(Registration.REJECTION);
        registration.setRejectionReason(reason);
        registrationMapper.updateById(registration);
    }

    /**
     * 历史报名查询
     *
     * @param pageNo 页码
     * @param pageSize 该页面数据数量
     * @param status  报名状态：1、已报名 2、已取消 3、已通过 4、已拒绝
     */
    @Override
    public PageResult pageQueryUser(Long pageNo, Long pageSize, Integer status) {
        Page<Registration> page = Page.of(pageNo, pageSize);

        RegistrationPageQueryDTO registrationPageQueryDTO=new RegistrationPageQueryDTO();
        registrationPageQueryDTO.setStatus(status);
        registrationPageQueryDTO.setUserId(BaseContext.getCurrentId());
        Page<Registration> p = lambdaQuery()
                .eq(registrationPageQueryDTO.getUserId()!=null,Registration::getUserId, registrationPageQueryDTO.getUserId())
                .eq(registrationPageQueryDTO.getStatus()!=null,Registration::getStatus, registrationPageQueryDTO.getStatus())
                .orderByDesc(Registration::getSignUpTime)
                .page(page);
        return new PageResult(p.getTotal(),p.getPages(),p.getRecords());
    }
}
